﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using TwitterAPI;
using System.Windows;
using VsSpeakerCompanion;
using System.ComponentModel.Composition;
using System.Windows.Threading;

namespace CoolnessWidget
{
    /// <summary>
    /// Allows the audience to express if they think the presentation is cool or not cool.
    /// </summary>
    class CoolWidget : IWidget
    {
        // our UI
        private CoolView view;
        // reference to core context
        private Context context;
        // lists to keep track of feedback
        private List<string> coolVoters;
        private List<string> notCoolVoters;

        public CoolWidget(Context context, TwitterService twitterService)
        {
            this.context = context;
            this.view = new CoolView();

            coolVoters = new List<string>();
            notCoolVoters = new List<string>();

            // register the two feedback messages this widget understands
            twitterService.RegisterCommand("is cool", ProcessCoolMessages);
            twitterService.RegisterCommand("is not cool", ProcessNotCoolMessages);
        }

        /// <summary>
        /// Handles 'is cool' received messages
        /// </summary>
        /// <param name="feedItems"></param>
        private void ProcessCoolMessages(IEnumerable<FeedItem> feedItems)
        {
            // each user has one vote max but it can be changed anytime
            feedItems.ToList().ForEach(item => { if (notCoolVoters.Contains(item.User)) notCoolVoters.Remove(item.User); });
            feedItems.ToList().ForEach(item => { if (!coolVoters.Contains(item.User)) coolVoters.Add(item.User); });
            // update UI based on new feedback
            UpdateVotesInVisualElement();
        }

        /// <summary>
        /// Handles 'is not cool' received messages
        /// </summary>
        /// <param name="feedItems"></param>
        private void ProcessNotCoolMessages(IEnumerable<FeedItem> feedItems)
        {
            // each user has one vote max but it can be changed anytime
            feedItems.ToList().ForEach(item => { if (coolVoters.Contains(item.User)) coolVoters.Remove(item.User); });
            feedItems.ToList().ForEach(item => { if (!notCoolVoters.Contains(item.User)) notCoolVoters.Add(item.User); });
            // update UI based on new feedback
            UpdateVotesInVisualElement();
        }

        /// <summary>
        /// Handles the update of the five different UI possible states based on the received feeback
        /// </summary>
        private void UpdateVotesInVisualElement()
        {
            double coolPerc = Convert.ToDouble(coolVoters.Count) / Convert.ToDouble(coolVoters.Count + notCoolVoters.Count);
            int score = Convert.ToInt32(coolPerc * 40.0);
            view.Dispatcher.Invoke(new Action<int>(scoreArgument => { view.Score = scoreArgument; }), score);
            UpdateVotesInContext();
        }

        public UIElement VisualElement
        {
            get
            {
                // return our UI
                return view;
            }
        }

        /// <summary>
        /// Reset data to its original state
        /// </summary>
        public void Reset()
        {
            this.coolVoters = new List<string>();
            this.notCoolVoters = new List<string>();
            UpdateVotesInContext();
            view.Score = 25;
        }

        /// <summary>
        /// Publish our vote count to the core context for others to consume
        /// </summary>
        /// <remarks>
        /// The StartStopSession will be reading this count
        /// </remarks>
        private void UpdateVotesInContext()
        {
            this.context.AddProperty("coolVotes", this.coolVoters.Count);
            this.context.AddProperty("notCoolVotes", this.notCoolVoters.Count);
        }

    }
}